#include <iostream>
#include <stdio.h>  
#include <time.h>

#include "Parser/Parser.h"
#include "DGMatrix.h"
#include "DGIntMatrix.h"
#include "mesh.h"
#include "functionSpace.h"
#include "timeIntegrator.h"
#include "initialSol.h"
#include "saveGmsh.h"
#include "model.h"
#include <omp.h>

using namespace std;
extern int yyCMDparse();
void SetParameters(ClassParameter&);

typedef vector<DGMatrix>       SolContainer;
typedef vector<FunctionSpace*> FsContainer;

int main(int argc, char** argv)
{
  cout << " _____________________________________________________________"  << endl;
  cout << "|                                                             |" << endl;
  cout << "|                    *** MyDGM 2D ***                         |" << endl;
  cout << "|             Autor: Guillaume Verheylewegen                  |" << endl;
  cout << "|_____________________________________________________________|" << endl;

#ifdef DEBUG
cout << "[compiling] ---> Debug mode" << endl;
#endif
#ifdef MY_OPENMP
cout << "[compiling] ---> blas_dgemm using OpenMP" << endl;
#endif
  
  #pragma omp parallel for
  for(int i=0;i<10;i++){int a=1+i;}
  
  double tstart = omp_get_wtime();

  // --- Read InputFile --------------------------------------------------------
  
  ClassParameter& param = Parser::instance().add("My2DProblem"); SetParameters(param);
  FILE* fp = freopen(argv[1],"r", stdin); yyCMDparse();

  // --- Set nb of threads -----------------------------------------------------

  int nbProcs = param.getInteger("NbThreads");
  cout << "[CPU] - nb of threads ----------> " << nbProcs << endl;	
  omp_set_num_threads(nbProcs);

  
  // --- Build directories -----------------------------------------------------
  
  system("rm -r output");
  system("mkdir output");

  // --- Build mesh topology ---------------------------------------------------
  
  Mesh mesh(param);

  // --- Build Function Space --------------------------------------------------
  
  int order = param.getInteger("Order");
  cout << "[FctSpace] - basis -------------> " << "Lagrange"  << endl;	        //NOT YET IMPLEMENTED
  cout << "[FctSpace] - order -------------> " << order       << endl;	
  
  FsContainer fs;
  for(vector<elmtType>::const_iterator eTIt = mesh.elmtGmshType.begin();eTIt!= mesh.elmtGmshType.end();++eTIt){
    fs.push_back(FunctionSpaceFactory::CreateNewFunctionSpace((FctType)*eTIt,order));
  }

  // --- Output object ---------------------------------------------------------

  SaveOutputGmsh output(&mesh,&fs);

  // --- Initialize initial solution -------------------------------------------
  
  InitialSolution initSol(&mesh,&fs,&output,param);

  // --- Build model -----------------------------------------------------------

  Model model(&mesh,&fs,&output,param);   

  // --- Build time intergrator ------------------------------------------------
  
  TimeIntegrator* ti = TimeIntegratorFactory::CreateNewTimeIntegrator(&model,param);
  ti->advanceInTime(&initSol);
  
  double tend = omp_get_wtime();
  printf ("Total elapsed time is %.6lf seconds\n",tend-tstart);
  
  cout << " _____________________________________________________________"  << endl;
  cout << "|                                                             |" << endl;
  cout << "|                      *** THE END ***                        |" << endl;
  cout << "|_____________________________________________________________|" << endl;
}